package DataBase;
import java.util.HashSet;
import org.hibernate.Session;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import java.util.List; 
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.Query; 

import Log.Log;


/**
* Description : connection of the tables Tags ,Tag_File and Files
* <p>
*
*@author Danielle
*/
public class MenuTag_File {
	static  SessionFactory sessionFactory;
	
	/**
	* Description Ctor
	*/
	public MenuTag_File()
	{
		sessionFactory = new Configuration().configure().buildSessionFactory();
	}
	
	
	/**
	* Description this function add assosiation from file to tag
	* @param String FileName
	* @param String TagName
	* @return int
	*/
	public int ConnectTag_File(String FileName,String TagName)
	{
		
    	Session session = sessionFactory.openSession();
        Transaction transaction = null;
        try {
            transaction = session.beginTransaction();
            ///if the file is not exist add it - also for the tag
            if (!fileIsExist(FileName))
            	addFile(FileName);
           
            if(!TagIsExist(TagName))
            	addTag(TagName);           
            ///take the tag and the file from DB
            Query query=session.createQuery("SELECT t from TagDB t WHERE t.tagName=:TagName");
    		query.setParameter("TagName", TagName);
    		Query query2=session.createQuery("SELECT t from FileDB t WHERE t.fileName=:FileName");
    		query2.setParameter("FileName", FileName);
    		///connect them :
    		Iterator it;
    		int num;
    		it=query.iterate();
    		TagDB tag=(TagDB)it.next();
    		it=query2.iterate();
    		FileDB file=(FileDB)it.next();
    		Set<TagDB> hashTag=file.getTags();
    		hashTag.add(tag);
    		file.setTags(hashTag);
    		session.update(file);
            transaction.commit();

        } catch (HibernateException e) {
            transaction.rollback();
            
            e.printStackTrace();
        } finally {
            session.close();
        }
		
		return 1;
	}
	
	/**
	* Description delete a file
	* @param String FileName
	* @return boolean
	*/
	public boolean delFile(String FileName)
	{
		///if the file is not exist return false
		if(!fileIsExist(FileName))
			return false;
		///find the file and delete it
		Session session = sessionFactory.openSession();
		Transaction transaction  = session.beginTransaction();
		Query query=session.createQuery("SELECT t from FileDB t WHERE t.fileName=:FileName");
		query.setParameter("FileName", FileName);
		List list=query.list();
		 if(!list.isEmpty())
		 {
			 Iterator it=query.iterate();
			 FileDB file=(FileDB)it.next();
			 session.delete(file);
			 transaction.commit();
		 }
		

		session.close();
		return true;
		
		
	}
	
	/**
	* Description delete a Tag
	* @param String TagName
	* @return boolean
	*/
	public boolean delTag(String TagName)
	{
		///if the tag is not exist return false
		if(!TagIsExist(TagName))
			return false;
		///find the tag and delete it
		Session session = sessionFactory.openSession();
		Query query=session.createQuery("SELECT t from TagDB t WHERE t.tagName=:TagName");
		query.setParameter("TagName", TagName);
		Transaction transaction  = session.beginTransaction();
		 
		Iterator it=query.iterate();
		TagDB tag=(TagDB)it.next();
		session.delete(tag);
		transaction.commit();

		session.close();
		new Log("Delete the tag: "+TagName);
		return true;
		
		
	}

	/**
	* Description addTag
	* @param String TagName
	* @return boolean
	*/
	public boolean addTag(String TagName)
	{
		///open session :
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		///if the tag is already exist:
		if(TagIsExist(TagName))
		{
			session.close();
			return false;
		}
		///else:
		TagDB tags=new TagDB(TagName);// create new Tags object
		session.saveOrUpdate(tags); // save Tags
		session.getTransaction().commit();
		session.close();
		return true;

		
		
	}

	/**
	* Description addFile
	* @param String FileName
	* @return boolean
	*/
	public boolean addFile(String FileName)
	{
		///open session :
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		///if the file is already exist:
		if(fileIsExist(FileName))
		{
			session.close();
			return false;
		}
		///else:
		FileDB file=new FileDB(FileName);// create new File object
		session.saveOrUpdate(file); // save Tags
		session.getTransaction().commit();
		session.close();
		return true;
	}

	/**
	* Description this function return a list of tags of a file
	* @param String FileName
	* @return String[]
	*/
	public String[] AllTagsOfFile(String FileName)
	{
		///if the file is not exist:
		if (!fileIsExist(FileName))
			return null;
		///else - open a session
		Session session = sessionFactory.openSession();
		Query query=session.createQuery("SELECT t from FileDB t WHERE t.fileName=:FileName");
		query.setParameter("FileName", FileName);
		Iterator it;
		it=query.iterate();
		FileDB file=(FileDB)it.next();
		Set<TagDB> hashTag=file.getTags();
		TagDB tagTemp;
		it=hashTag.iterator();
		 ///and run over it - and add it to returnString
		int size=hashTag.size();
		String[] returnString=new String[size];
		int i=0;
		while(it.hasNext())
		{
			tagTemp=(TagDB)it.next();
			returnString[i]=tagTemp.getTagName();
			i++;
		}		
		session.close();
		return returnString;
		
	}

	/**
	* Description this function return a list of files that tagged with "TagName"
	* @param String TagName
	* @return String[]
	*/
	public String[] AllFilesInTag(String TagName)
	{
		///if the tag is not exist:
		if (!TagIsExist(TagName))
			return null;
		///else - open a session
		Session session = sessionFactory.openSession();
		Query query=session.createQuery("SELECT t from TagDB t WHERE t.tagName=:TagName");
		query.setParameter("TagName", TagName);
		
		Query query2=session.createQuery("SELECT t from FileDB t  ");
		
		Iterator it;
		it=query.iterate();
		TagDB tag=(TagDB)it.next();
		Set<TagDB> hashTag;
		FileDB file;
		it=query2.iterate();
		int size=0;
		while(it.hasNext())
		{
			file=(FileDB)it.next();
			hashTag=file.getTags();
			if(hashTag.contains(tag))
			{
				size++;
			}
		}
		///and run over it - and add it to returnString
		String[] returnString=new String[size];
		int i=0;
		it=query2.iterate();
		while(it.hasNext())
		{
			file=(FileDB)it.next();
			hashTag=file.getTags();
			if(hashTag.contains(tag))
			{
				returnString[i]=file.getfileName();
				i++;
			}
		}		
		session.close();
		return returnString;
		
	}

	/**
	* Description this function return the id of file
	* @param String FileName
	* @return int
	*/
	public int getFileId(String FileName)
	{
		///open session
		Session session = sessionFactory.openSession();
		///find a file with the same name :
		Query query=session.createQuery("SELECT t.fileId from FileDB t WHERE t.fileName=:FileName");
		query.setParameter("FileName", FileName);
		List list=query.list();
		if(list.isEmpty())
		{
			System.out.println("DB: No File Named:" + FileName);
			session.close();
			return 0;
		}
		Iterator it;
		int num;
		it=query.iterate();
		///get the id:
		Long id=(Long)it.next();
		String str2 =id.toString();
		num=Integer.parseInt(str2.trim());
		session.close();
		return num;
		
	}
	
	/**
	* Description this function return the id of tag
	* @param String TagName
	* @return int
	*/
	public int getTagId(String TagName)
	{
		///open session
		Session session = sessionFactory.openSession();
		///find a tag with the same name :
		Query query=session.createQuery("SELECT t.tagId from TagDB t WHERE t.tagName=:TagName");
		query.setParameter("TagName", TagName);
		List list=query.list();
		if(list.isEmpty())
		{
			System.out.println("DB: No Tag Named:" + TagName);
			session.close();
			return 0;
		}
		Iterator it;
		int num;
		it=query.iterate();
		///get the id:
		Long id=(Long)it.next();
		String str2 =id.toString();
		num=Integer.parseInt(str2.trim());
		session.close();
		return num;
	}


	/**
	* Description fileIsExist
	* @param String FileName
	* @return boolean
	*/
	public boolean fileIsExist(String FileName)
	{
		///open session
		Session session = sessionFactory.openSession();
		///find a file with the same name :
		Query query=session.createQuery("SELECT t.fileId from FileDB t WHERE t.fileName=:FileName");
		query.setParameter("FileName", FileName);
		List list=query.list();
		///send if it exist:
		if(!list.isEmpty())
		{
			session.close();
			return true;
		}
		else
		{
			session.close();
			return false;
		}
	}


	/**
	* Description TagIsExist
	* @param String TagName
	* @return boolean
	*/
	public boolean TagIsExist(String TagName)
	{
		///open session
		Session session = sessionFactory.openSession();
		///find a tag with the same name :
		Query query=session.createQuery("SELECT t.tagId from TagDB t WHERE t.tagName=:TagName");
		query.setParameter("TagName", TagName);
		List list=query.list();
		///send if it exist:
		if(!list.isEmpty())
		{
			session.close();
			return true;
		}
		else
		{
			session.close();
			return false;
		}
	}
	/**
	* Description getFiles
	* @return String[]
	*/
	public String[] getFiles()
	{
		///open session
		Session session = sessionFactory.openSession();
		///find all the files
		Query query=session.createQuery("SELECT t from FileDB t ");

		Iterator it;
		it=query.iterate();
		FileDB file;
		int size=(query.list()).size();
		///run over them 
		String[] returnString=new String[size];
		int i=0;
		while(it.hasNext())
		{
			file=(FileDB)it.next();
			returnString[i]=file.getfileName();
			i++;
		}		
		session.close();
		return returnString;
		
		
	}
	
	/**
	* Description getTags
	* @return String[]
	*/
	public String[] getTags()
	{
		///open session
		Session session = sessionFactory.openSession();
		///find all the tags
		Query query=session.createQuery("SELECT t from TagDB t ");

		Iterator it;
		it=query.iterate();
		TagDB tag;
		int size=(query.list()).size();
		///run over them 
		String[] returnString=new String[size];
		int i=0;
		while(it.hasNext())
		{
			tag=(TagDB)it.next();
			returnString[i]=tag.getTagName();
			i++;
		}		
		session.close();
		return returnString;
	}
	
	/**
	* Description deleteDB
	*/
	public void deleteDB()
	{
		///open session
		Session session = sessionFactory.openSession();
		///find all the tags
		Query query=session.createQuery("SELECT t from TagDB t ");
		Iterator it;
		it=query.iterate();
		TagDB tag;
		///delete all the tags:
		while(it.hasNext())
		{
			tag=(TagDB)it.next();
			delTag(tag.getTagName());
		}		
		///find all the files
		query=session.createQuery("SELECT t from FileDB t ");
		it=query.iterate();
		FileDB file;
		///delete all the files:
		while(it.hasNext())
		{
			file=(FileDB)it.next();
			delFile(file.getfileName());
		}	
		session.close();
	}
}